﻿using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;

namespace Cyss.Core.Repository.EF
{
    /// <summary>
    /// 基础默认增删改查服务类
    /// </summary>
    /// <typeparam name="TEntity"></typeparam>
    public class BaseService<TEntity> : IBaseService<TEntity> where TEntity : BaseEntity
    {
        #region 字段
        /// <summary>
        /// 数据仓储
        /// </summary>
        protected readonly IRepository<TEntity> _repository;

        /// <summary>
        /// 当前工作上下文
        /// </summary>
        protected IWorkContext _workContext { set; get; }
        #endregion

        #region 构造函数

        /// <summary>
        /// 仓储
        /// </summary>
        /// <param name="repository"></param>
        public BaseService(IRepository<TEntity> repository)
        {
            _repository = repository;
            _workContext = IOCEngine.Resolve<IWorkContext>();
        }

        #endregion

        #region 数据方法

        /// <summary>
        ///  根据主键获取数据(基础方法)
        /// </summary>
        /// <param name="Id">主键</param>
        /// <returns>数据</returns>
        public virtual TEntity GetById(object Id, bool IsNoTracking = false)
        {
            if (Id == null)
                return null;
            if (IsNoTracking == false)
                return _repository.GetById(Id);
            return _repository.TableNoTracking.FirstOrDefault(x => x == Id);
        }


        /// <summary>
        ///新增数据(基础方法)
        /// </summary>
        /// <param name="model">数据</param>
        public virtual void Insert(TEntity model)
        {
            if (model == null)
                throw new ArgumentNullException("model");
            _repository.Insert(model);
        }

        /// <summary>
        ///新增数据(基础方法)
        /// </summary>
        /// <param name="model">数据</param>
        public virtual void Insert(IEnumerable<TEntity> models)
        {
            if (models == null || !models.Any())
                throw new ArgumentNullException("models");
            _repository.Insert(models);
        }

        /// <summary>
        ///     更新数据(基础方法)
        /// </summary>
        /// <param name="model">数据</param>
        public virtual void Update(TEntity model)
        {
            if (model == null)
                throw new ArgumentNullException("model");
            _repository.Update(model);
        }
        /// <summary>
        ///     更新数据(基础方法)
        /// </summary>
        /// <param name="model">数据</param>
        public virtual void Update(IEnumerable<TEntity> models)
        {
            if (models == null || !models.Any())
                throw new ArgumentNullException("model");
            _repository.Update(models);
        }

        /// <summary>
        ///     删除 数据(基础方法)
        /// </summary>
        /// <param name="model">数据</param>
        public virtual void Delete(TEntity model)
        {
            if (model == null)
                throw new ArgumentNullException("model");
            _repository.Delete(model);
        }

        /// <summary>
        ///     删除 数据(基础方法)
        /// </summary>
        /// <param name="model">数据</param>
        public virtual void Delete(IEnumerable<TEntity> models)
        {
            if (models == null)
                throw new ArgumentNullException("models");
            _repository.Delete(models);
        }

        /// <summary>
        /// 删除数据(基础方法)
        /// </summary>
        /// <param name="model">数据</param>
        public virtual void Delete(Expression<Func<TEntity, bool>> predicate)
        {
            if (predicate == null)
                throw new ArgumentNullException("predicate");
            _repository.TableNoTracking.Where(predicate).ExecuteDelete();
        }
        /// <summary>
        ///删除数据(基础方法)
        /// </summary>
        /// <param name="model">收藏表</param>
        public virtual void Delete(int Id)
        {
            if (Id <= 0)
            {
                return;
            }
            _repository.Delete(Id);
        }

        /// <summary>
        ///     删除 数据(基础方法)
        /// </summary>
        /// <param name="model">收藏表</param>
        public virtual void Delete(IEnumerable<int> ids)
        {
            if (ids == null || ids.Count() <= 0)
            {
                return;
            }
            _repository.Delete(ids);
        }

        /// <summary>
        /// 满足条件的数据是否存在(基础方法)
        /// </summary>
        /// <param name="predicate">条件</param>
        /// <returns>是否存在</returns>
        public virtual bool Exists(Expression<Func<TEntity, bool>> predicate)
        {
            var query = _repository.TableNoTracking;
            query = query.Where(predicate);
            return query.Any();
        }

        /// <summary>
        ///  获取满足条件的第一条数据(基础方法)
        /// </summary>
        /// <param name="predicate">查询条件</param>
        /// <param name="IsNoTracking">是否进行实体跟踪,如果查询的对象不用于修改更新默认即可，实体跟踪会消耗资源</param>
        /// <returns>数据集合</returns>
        public virtual TEntity FirstOrDefault(Expression<Func<TEntity, bool>> predicate = null, bool IsNoTracking = true)
        {
            IQueryable<TEntity> query = IsNoTracking ? _repository.TableNoTracking : _repository.Table;
            if (predicate != null)
            {
                query = query.Where(predicate);
            }
            return query.FirstOrDefault();
        }



        /// <summary>
        ///  获取所有的  数据(基础方法)
        /// </summary>
        /// <param name="predicate">查询条件</param>
        /// <param name="IsNoTracking">是否进行实体跟踪,如果查询的对象不用于修改更新默认即可，实体跟踪会消耗资源</param>
        /// <returns>数据集合</returns>
        public virtual IList<TEntity> Gets(Expression<Func<TEntity, bool>> predicate = null, bool IsNoTracking = true)
        {
            IQueryable<TEntity> query = IsNoTracking ? _repository.TableNoTracking : _repository.Table;
            if (predicate != null)
            {
                query = query.Where(predicate);
            }

            return query.ToList();
        }

        /// <summary>
        /// 分页获取 数据(基础方法)
        /// </summary>
        /// <param name="searchModel">查询model</param>
        /// <param name="showHidden"></param>
        /// <returns></returns>
        public virtual IPagedList<TEntity> GetPageLists(BaseSearchModel searchModel)
        {
            var query = _repository.TableNoTracking;
            var entitys = new PagedList<TEntity>(query, searchModel);
            return entitys;
        }

        #endregion
    }
}
